package com.kjhxtc.restfulrunner;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ArrayUtil;
import lombok.SneakyThrows;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContexts;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

/**
 * @author 杜神
 * @version 1.0
 * @since 2022/3/16 10:29
 */
public class RestfulClient {
    private final CloseableHttpClient httpClient;

    public RestfulClient(String ip, Integer port) {
        this(ip, port, 10, 5);
    }

    @SneakyThrows
    public RestfulClient(String ip, Integer port, int maxTotal, int maxPerRoute) {
        //采用绕过验证的方式处理https请求
        SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();

        //设置协议http和https对应的处理socket链接工厂的对象
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", new SSLConnectionSocketFactory(sslcontext, NoopHostnameVerifier.INSTANCE))
                .build();

        //设置http的状态参数
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(5000)
                .setConnectTimeout(5000)
                .setConnectionRequestTimeout(5000)
                .build();
        HttpHost target = new HttpHost(ip, port);
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        connectionManager.setMaxTotal(maxTotal);//客户端总并行链接最大数
        connectionManager.setDefaultMaxPerRoute(maxPerRoute);//每个主机的最大并行链接数
        connectionManager.setMaxPerRoute(new HttpRoute(target), maxPerRoute);
        connectionManager.setValidateAfterInactivity(4900);

        this.httpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager)
                .build();

    }

    public CloseableHttpClient getHttpClient() {
        return httpClient;
    }


    public synchronized static void traceRequest(HttpUriRequest request) {
        if (Log.IS_TRACE) {
            Log.trace("===========================request begin {}================================================");
            Log.trace("URI         : {}", request.getURI());
            Log.trace("Method      : {}", request.getMethod());
            Log.trace("Headers     : {}", ArrayUtil.toString(request.getAllHeaders()));
            Log.trace("Request body: {}", request.toString());
            Log.trace("==========================request end================================================");
        }
    }

    public synchronized static void traceResponse(HttpResponse response) throws IOException {
        if (Log.IS_TRACE) {
            HttpEntity entity = response.getEntity();
            InputStream content = entity.getContent();
            String body = IoUtil.read(content, true).toString(StandardCharsets.UTF_8);
            Log.trace("============================response begin {}==========================================");
            Log.trace("Status code  : {}", response.getStatusLine().getStatusCode());
            Log.trace("Status text  : {}", response.getStatusLine().getReasonPhrase());
            Log.trace("Headers      : {}", ArrayUtil.toString(response.getAllHeaders()));
            Log.trace("Response body: {}", body);
            Log.trace("=======================response end=================================================");
        }
    }
}
